package com.example.config;

import com.example.pojo.UserForShiro;
import com.example.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author: 21050134
 * @date: 2023/11/2 10:43
 * @description:
 */
//自定义Realm
public class UserRealm extends AuthorizingRealm {

	@Autowired
	UserService userService;
	//执行授权逻辑
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){
		//认证之后，如果前端shiro标签中有出现需要权限的标签，或者过滤器中某个链接需要权限，就会进行认证
		System.out.println("执行了=》授权逻辑 PrincipalCollection");
		//给资源授权
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		//拿到当前登陆的对象
		Subject subject = SecurityUtils.getSubject();
		UserForShiro currentPrincipal = (UserForShiro)subject.getPrincipal();//拿到user对象
		//设置当前用户权限，从数据胡查询
		info.addStringPermission(currentPrincipal.getPerms());
		//添加角色
		info.addRole(currentPrincipal.getRole());

		return info;
	}

	//执行认证逻辑
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token ) throws AuthenticationException {
		System.out.println("执行了=》认证逻辑 AuthenticationToken");
      /*   //假设数据库的用户名和密码
		String name = "root";
		String password = "123456";
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
		if(!usernamePasswordToken.getUsername().equals(name)){
			return null; //shiro底层就会抛出 UnknownAccountException
		}
        //验证密码 SimpleAuthenticationInfo
		// shiro会自动帮我们验证！重点是第二个参数就是要验证的密码！
		return new SimpleAuthenticationInfo("",password,"");*/

		UsernamePasswordToken userToken = (UsernamePasswordToken)token;
		UserForShiro user = userService.queryUserByName(userToken.getUsername());
		if(user == null){
			return null;//抛出异常 UnknownAccountException
		}
		//为了完美，我们在用户登录后应该把信息放到Session中，我们完善下！在执行认证逻辑时候，加入session
		Subject currentSubject = SecurityUtils.getSubject();
		Session session = currentSubject.getSession();
		session.setAttribute("loginUser",user);
		//第一个参数类型principal 当事人；首要的；最主要的 将user对象传递给上面的授权操作
		return new SimpleAuthenticationInfo(user,user.getPwd(),"");
	}

	/**
	 * 重写方法,清除当前用户的的 授权缓存
	 * @param principals
	 */
	@Override
	public void clearCachedAuthorizationInfo(PrincipalCollection principals){
      super.clearCachedAuthorizationInfo(principals);
	}

	/**
	 * 重写方法，清除当前用户的 认证缓存
	 * @param principals
	 */
	@Override
	public void clearCachedAuthenticationInfo(PrincipalCollection principals){
		super.clearCachedAuthenticationInfo(principals);
	}

	@Override
	public void clearCache(PrincipalCollection principals){
		super.clearCache(principals);
	}

	/**
	 * 自定义方法：清除所有 授权缓存
	 */
	public void clearAllCachedAuthorizationInfo(){
		getAuthenticationCache().clear();
	}

	/**
	 * 自定义方法：清除所有 认证缓存
	 */
	public void clearAllCachedAuthenticationInfo() {
		getAuthenticationCache().clear();
	}

	/**
	 * 自定义方法：清除所有的  认证缓存  和 授权缓存
	 */
	public void clearAllCache() {
		clearAllCachedAuthenticationInfo();
		clearAllCachedAuthorizationInfo();
	}


}
